package com.xltq.controller;

import com.xltq.entity.User;
import com.xltq.service.IUserService;
import com.xltq.service.impl.IUserServiceImpl;
import com.xltq.utils.Base64Utils;
import com.xltq.utils.Constants;
import com.xltq.utils.MD5Utils;
import com.xltq.utils.RandomUtils;
import org.apache.commons.beanutils.BeanUtils;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import javax.swing.*;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.Map;
import java.util.Objects;

//统一处理用户模块的操作(注册,登录,注销登录)
@WebServlet("/user")
public class UserController extends BaseServlet {

    //用户名检查
    public String check(HttpServletRequest request,HttpServletResponse response) throws  Exception{
        //1.获取用户名
        String username = request.getParameter("username");
        if(Objects.isNull(username)){
            //封装Constants中 提供两个常量表示(就是为了Ajax中判断使用) 用户注册与无法注册
            return Constants.HAS_USER;// 表示不能注册
        }
        //2.调用业务层逻处理用户名检查
        IUserService userService = new IUserServiceImpl();
        boolean b = userService.checkeUser(username);
        //如果为true 证明用户存在(用户名不可以使用)  否则 不存在用户名可用
        if(b){
            return  Constants.HAS_USER;
        }
        return Constants.NOT_HAS_USER;
    }

    //用户注册
    public String register(HttpServletRequest request,HttpServletResponse response) throws  Exception{
        //1.工程已经导入了BeanUtils工具类,可以将大量数据一次性存储到Bean对象中
        //key就是input标签名字  value就是input标签的value值
        Map<String, String[]> parameterMap = request.getParameterMap();
        User user= new User();
        //2.调用BeanUtils工具类型将获取哦到所有数据注入到User对象
        try {
            BeanUtils.populate(user, parameterMap);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        //3.后台user表中列还有,通过注入到User对象中数据并不能对表中列完全赋值
        //3.1设置用户的激活状态
        //在constants中设置未激活常量
        user.setUstatus(Constants.USER_NOT_ACTIVE);
        //3.2设置用户角色
        //在constants中设置用户角色常量
        user.setUrole(Constants.ROLE_CUSTOMER);
        //3.3设置用户的激活码
        user.setCode(RandomUtils.createActive());
        //3.4用户的密码加密的存储不是明文存储
        user.setUpassword(MD5Utils.md5(user.getUpassword()));

        //4.调用业务层触发dao层进行数据存储
        IUserService userService = new IUserServiceImpl();

        try {
            //注册数据发生了异常,证明注册失败
            userService.registerUser(user);
        } catch (Exception e) {
            e.printStackTrace();
            //出现异常证明注册失败
            //需要修改JSP页面才能才能显示  ---> register.jsp
            //<%--修改这个位置 存在的request作用域总的数据所以需要删除session使用request作用域中数据--%>
            //<div>${requestScope.registerMsg}</div>
            request.setAttribute("registMsg", "注册失败");
            return  Constants.FORWARD+"/register.jsp";

        }

        return Constants.FORWARD+"/registerSuccess.jsp";
    }

    //验证激活码并激活
    public String active(HttpServletRequest request,HttpServletResponse response) throws  Exception{
         //1.获取调用回来之后激活码
        String c = request.getParameter("c");
        //2.将激活码进行Base64解码
        String code = Base64Utils.decode(c);
        //3.调用业务层触发dao层操作
        IUserService userService = new IUserServiceImpl();
        int i = userService.activeUser(code);
        if(i == Constants.ACTIVE_FAIL){
            //证明激活失败 项目中有一个同意错误信息展示页面 message.jsp
            //message.jsp页面中使用 作用域中msg对象, 只需要向这个对象中存数据就行
            request.setAttribute("msg", "未激活成功!");
        }else if(i == Constants.ACTIVE_SUCCESS){
            request.setAttribute("msg", "激活成功,请登录");
        }else{
            request.setAttribute("msg", "已经激活了");
        }
        return  Constants.FORWARD+"/message.jsp";

    }

    //----------------------------------------------------登录的Servlet操作----------------------------------------------------------
    //添加验证用户名是否正确操作
    public String checkloginUsername(HttpServletRequest request,HttpServletResponse response) throws  Exception{
        //1.获取用户名
        String username = request.getParameter("username");
        if(Objects.isNull(username)){
            //封装Constants中 提供两个常量表示(就是为了Ajax中判断使用)
            //ajax中get方法提供了 function(data) --> data参数
            //这个参数的判断是  data==0 所以  返回0 这个值让ajax进行判断
            return Constants.LOGIN_CHECK_NAME_ERROR;
        }
        //2.调用业务层逻处理用户名检查
        IUserService userService = new IUserServiceImpl();
        boolean b = userService.checkeUser(username);
        //如果为true 证明用户存在(用户名不可以使用)  否则 不存在用户名可用
        if(b){
            //   LOGIN_CHECK_NAME_RIGHT 值是1  用于ajax中判断
            return  Constants.LOGIN_CHECK_NAME_RIGHT;
        }
        return Constants.LOGIN_CHECK_NAME_ERROR;

    }
    //添加验证码验证逻辑
    public String checkCode(HttpServletRequest request,HttpServletResponse response) throws  Exception{
        //1.获取验证码
        String code = request.getParameter("code");
        //2.通过存存储在session作用域中数据进行验证吗判断
        HttpSession session = request.getSession();
        String code1 = (String)session.getAttribute("code");
        //3.判断是是否正确
        if(Objects.nonNull(code) && code.equalsIgnoreCase(code1)){
            //验证码不为空 并且输入的验证码等于生成的验证码 --> 返回值给Ajax进行判断
            //data==0   RIGHT_CODE值就是0用于正确判断
            return  Constants.RIGHT_CODE;
        }else{
            //  ERROR_CODE值就是1用于错误判断
            return  Constants.ERROR_CODE;
        }

    }

    //添加登录逻辑
    public String login(HttpServletRequest request,HttpServletResponse response) throws  Exception{
        //1.获取请求参数
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        //获取自动登录标识
        String auto = request.getParameter("auto");

        //2.调用业务层实现登录操作
        IUserService userService = new IUserServiceImpl();
        User user = userService.login(username, password);
        //判断user对象状态
        if(Objects.isNull(user)){
            //如果user对象是空的,证明不存在这个账户
            request.setAttribute("msg", "账户或密码错误");
            return Constants.FORWARD+"/login.jsp";
        }
        if(user.getUstatus().equals(Constants.USER_NOT_ACTIVE)){
            //用户是未激活状态
            request.setAttribute("msg", "账号未激活!");
            return Constants.FORWARD+"/login.jsp";
        }
        //在header.jsp页面中有一个loginUser的属性被使用,只需要向这个属性中光存储user对象即可
        //可以等路等存数据到loginUser中 ,相当修改了登录之后的headr栏
        //将原来 登录|注册 修改为  用户名|注销
        HttpSession session = request.getSession();
        session.setAttribute("loginUser",user);

        //实现自动登录 -->需要判断是否外界勾选了-->选择框
        if(Objects.isNull(auto)){
            //这个值为空就没有候选
            //将本地存储的用户cookie清空覆盖
            //在Constants中存储一个用户开个与密码的常量
            Cookie cookie = new Cookie(Constants.AUTO_NAME,"");
            //设置cookie可以被访问路径
            cookie.setPath("/"); //当前工程下都可以访问这个cookie
            cookie.setMaxAge(0);//立即销毁
            response.addCookie(cookie);
        }else{
            //自动登录2周
            //将content作为cookie中的value值进行存即(存储了用户名和密码)
            String content = username+Constants.FLAG+password;
            //因为cookie是存储在本地(客户端)所以加密处理
            content = Base64Utils.encode(content);
            Cookie cookie = new Cookie(Constants.AUTO_NAME, content);
            //设置cookie可以被访问路径
            cookie.setPath("/"); //当前工程下都可以访问这个cookie
            cookie.setMaxAge(14*24*60*60);//设置声明周期为2周
            response.addCookie(cookie);
        }
        return  Constants.FORWARD+"/index.jsp";

    }
    //添加注销逻辑
    public String logOut(HttpServletRequest request,HttpServletResponse response) throws  Exception{
        //1.清空session中存储的用户数据
        request.getSession().removeAttribute("loginUser");
        //2.将Cookie中存储的用用户数据进行清空操作
        Cookie cookie = new Cookie(Constants.AUTO_NAME,"");
        //设置cookie可以被访问路径
        cookie.setPath("/"); //当前工程下都可以访问这个cookie
        cookie.setMaxAge(0);//立即销毁
        response.addCookie(cookie);
        //3.转发到登录页面
        request.setAttribute("msg", "注销登录成功!");
        return  Constants.FORWARD+"/login.jsp";

    }

}
